﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YiYiTong.Rocket.Helper;
using YiYiTong.Rocket.Model;
using Jiguang.JPush;
using Jiguang.JPush.Model;

namespace YiYiTong.Rocket.Business
{
    /// <summary>
    /// 极光推送
    /// </summary>
    public class JpushBiz
    {
        #region Instance
        private JpushBiz()
        {
        }

        private static JpushBiz _instance;
        private static object _syncObject = new object();
        public static JpushBiz Instance
        {
            get
            {
                if (_instance == null)
                {
                    lock (_syncObject)
                    {
                        if (_instance == null)
                        {
                            _instance = new JpushBiz();
                        }
                    }
                }
                return _instance;
            }
        }
        #endregion

        private Random _rnd;
        public Random Rnd
        {
            get
            {
                if (_rnd == null)
                    _rnd = new Random(DateTime.Now.Ticks.GetHashCode());
                return _rnd;
            }
        }

        public static bool PushMsg(PushMessageRequest req)
        {
            string appkey = ConfigHelper.AppSetting<string>("jpush_appkey");
            string secret = ConfigHelper.AppSetting<string>("jpush_secret");
            string url = ConfigHelper.AppSetting<string>("jpush_url");

            JPushClient client = new JPushClient(appkey, secret);
            bool is_send = true;
            var payload = BuildNotifyPushMsg(req);
            try
            {
                HttpResponse result = client.SendPush(payload);
                if (result.StatusCode != System.Net.HttpStatusCode.OK)
                {
                    is_send = false;
                    LogHelper.Error(string.Format("极光消息推送失败，内容：{0} 错误：{1}",
                        req.Text, result.Content));
                }
            }
            catch (Exception ex)
            {
                LogHelper.Error(string.Format("极光消息推送异常，内容：{0} 错误：{1}",
                    req.Text, ex.StackTrace));
            }
            return is_send;

            #region 已失效 取消的方法
            //////List<PushPayload> pushMsgList = BuildPushMsg(req);

            //////bool is_send = true;
            //////HttpResponse result = null;
            //////foreach (var payload in pushMsgList)
            //////{
            //////    try
            //////    {
            //////        result = client.SendPush(payload);
            //////        if (result.StatusCode != System.Net.HttpStatusCode.OK)
            //////        {
            //////            is_send = false;
            //////            LogHelper.Error(string.Format("极光消息推送失败，内容：{0} 错误：{1}",
            //////                req.Text, result.Content));
            //////        }
            //////    }
            //////    catch (Exception ex)
            //////    {
            //////        LogHelper.Error(string.Format("极光消息推送异常，内容：{0} 错误：{1}",
            //////            req.Text, ex.StackTrace));
            //////    }
            //////}
            #endregion

            return is_send;
        }

        private static PushPayload BuildNotifyPushMsg(PushMessageRequest req)
        {
            PushPayload pushPayload = new PushPayload();
            List<string> platform = new List<string>();
            if (req.DeviceType == 3)//Android通知
            {
                platform.Add("android");
            }
            else if (req.DeviceType == 2)//ios
            {
                platform.Add("ios");
            }
            else //安卓和ios
            {
                platform.Add("android");
                platform.Add("ios");
            }
            pushPayload.Platform = platform;

            if (GetAudience(req) == null)
                pushPayload.Audience = "all";
            else
                pushPayload.Audience = GetAudience(req);


            pushPayload.Notification = new Notification
            {
                Alert = req.Alert,
                Android = new Android
                {
                    Alert = req.Alert,
                    Title = req.Title
                },
                IOS = new IOS
                {
                    Alert = req.Alert,
                    Badge = "+1"
                }
            };

            //如果是自定义消息，需要加以下部分
            /*
            var msginfo = new PushMsgInfo(req.MsgType.ToString(), req.Alert, req.Title, req.Text);
            string data = JsonHelper.SerializeNoSetting(msginfo);
            Message jpush_message = new Message();
            jpush_message.Title = req.Title;
            jpush_message.Content = data;
            pushPayload.Message = jpush_message;
            */

            if (ConfigHelper.AppSetting<string>("jpush_Env") == "product")
            {
                pushPayload.Options = new Options() { IsApnsProduction = true };
            }

            return pushPayload;
        }

        private static List<PushPayload> BuildPushMsg(PushMessageRequest req)
        {
            List<PushPayload> list = new List<PushPayload>();
            var msginfo = new PushMsgInfo(req.MsgType.ToString(), req.Alert, req.Title, req.Text);
            string data = JsonHelper.SerializeNoSetting(msginfo);

            Message jpush_message = new Message();
            jpush_message.Content = data;

            if (string.IsNullOrEmpty(req.Alert))
            {
                //自定义消息推送
                PushPayload pushPayload = new PushPayload();
                if (GetAudience(req) == null)
                    pushPayload.Audience = "all";
                else
                    pushPayload.Audience = GetAudience(req);
                pushPayload.Platform = GetPlatform(req);
                pushPayload.Message = jpush_message;
                if (ConfigHelper.AppSetting<string>("jpush_env") == "product")
                {
                    pushPayload.Options = new Options() { IsApnsProduction = true };
                }
                list.Add(pushPayload);
            }
            else
            {
                //通知类型推送
                if (req.DeviceType == 3)//Android通知
                {
                    PushPayload pushPayload = new PushPayload();
                    if (GetAudience(req) == null)
                        pushPayload.Audience = "all";
                    else
                        pushPayload.Audience = GetAudience(req);
                    pushPayload.Platform = "android";
                    pushPayload.Message = jpush_message;
                    pushPayload.Notification = new Notification()
                    {
                        Alert = req.Title,
                        Android = new Android()
                        {
                            Alert = req.Alert,
                            Title = req.Title
                        }
                    };
                    list.Add(pushPayload);
                }
                else if (req.DeviceType == 2)//IOS通知
                {
                    PushPayload pushPayload = new PushPayload();
                    if (GetAudience(req) == null)
                        pushPayload.Audience = "all";
                    else
                        pushPayload.Audience = GetAudience(req);
                    pushPayload.Platform = "ios";
                    pushPayload.Message = jpush_message;
                    pushPayload.Notification = new Notification()
                    {
                        Alert = req.Alert,
                        IOS = new IOS()
                        {
                            Alert = req.Alert,
                            Badge = req.Badge.ToString(),
                            Sound = req.Sound
                        }
                    };
                    if (ConfigHelper.AppSetting<string>("jpush_Env") == "product")
                    {
                        pushPayload.Options = new Options() { IsApnsProduction = true };
                    }
                    list.Add(pushPayload);
                }
                else
                {
                    //所有平台时，Android一条通知，IOS一条通知
                    PushPayload pushPayload = new PushPayload();
                    if (GetAudience(req) == null)
                        pushPayload.Audience = "all";
                    else
                        pushPayload.Audience = GetAudience(req);
                    pushPayload.Platform = "android";
                    pushPayload.Message = jpush_message;
                    pushPayload.Notification = new Notification()
                    {
                        Alert = req.Title,
                        Android = new Android()
                        {
                            Alert = req.Alert,
                            Title = req.Title
                        }
                    };
                    list.Add(pushPayload);

                    //ios通知
                    PushPayload iosPushPayload = new PushPayload();
                    if (GetAudience(req) == null)
                        iosPushPayload.Audience = "all";
                    else
                        iosPushPayload.Audience = GetAudience(req);
                    iosPushPayload.Platform = "ios";
                    iosPushPayload.Message = jpush_message;
                    iosPushPayload.Notification = new Notification()
                    {
                        Alert = req.Alert,
                        IOS = new IOS() { Alert = req.Alert }
                    };
                    if (ConfigHelper.AppSetting<string>("jpush_Env") == "product")
                    {
                        iosPushPayload.Options = new Options() { IsApnsProduction = true };
                    }
                    list.Add(iosPushPayload);
                }
            }
            return list;
        }

        private static Audience GetAudience(PushMessageRequest req)
        {
            Audience audience = new Audience();
            if (req.PushType == 1)
                audience = null;
            else if (req.PushType == 2)
            {
                audience.Tag = new List<string>();
                foreach (var item in StringHelper.Split(req.Tags, ','))
                    audience.Tag.Add(item);
            }
            else if (req.PushType == 3)
            {
                audience.Alias = new List<string>();
                foreach (var item in StringHelper.Split(req.Alias, ','))
                    audience.Alias.Add(item);
            }
            else if (req.PushType == 4)
            {
                audience.RegistrationId = new List<string>();
                foreach (var item in StringHelper.Split(req.DeviceTokens, ','))
                    audience.RegistrationId.Add(item);
            }
            else
                throw new ApplicationException("未处理PushType(" + req.PushType + ")");
            return audience;
        }

        private static string GetPlatform(PushMessageRequest req)
        {
            if (req.DeviceType == 1)
            {
                //所有平台
                return "all";
            }
            else if (req.DeviceType == 2)
            {
                //IOS平台
                return "ios";
            }
            else if (req.DeviceType == 3)
            {
                //Android 平台
                return "android";
            }
            else
                throw new ApplicationException("未处理DeviceType(" + req.DeviceType + ")");
        }
    }

    public class PushMessageRequest
    {
        /// <summary>
        /// 推送目标, 必填参数,
        /// 说明 1：全部用户(忽略标签和别名)   
        ///      2：多个标签(标签必填)  
        ///      3：多个别名(别名必填)  
        ///      4：多个注册ID(注册ID必填)
        /// </summary>
        public int PushType { get; set; }
        /// <summary>
        /// 用户标签
        /// </summary>
        public string Tags { get; set; }
        /// <summary>
        /// 用户别名
        /// </summary>
        public string Alias { get; set; }
        /// <summary>
        /// 注册id
        /// </summary>
        public string DeviceTokens { get; set; }
        /// <summary>
        /// 推送平台  1：全部   2：IOS   3：Android
        /// </summary>
        public int DeviceType { set; get; }
        /// <summary>
        /// 推送标题, 可选参数
        /// </summary>
        public string Title { set; get; }
        /// <summary>
        /// 推送内容, 可选参数
        /// </summary>
        public string Text { set; get; }
        /// <summary>
        /// 通知内容, 消息类型为[通知]时必须
        /// </summary>
        public string Alert { get; set; }
        /// <summary>
        /// 消息类型, 必填参数, 说明 1：系统消息 2 个人消息
        /// </summary>
        public int MsgType { get; set; }
        /// <summary>
        /// 通知声音, 可选参数, 仅对IOS有效, 用于控制IOS收到通知时的提示声音
        /// </summary>
        public string Sound { get; set; }

        /// <summary>
        /// 应用角标,可选参数, 仅对IOS有效,如果小于0，表示不改变角标数字；否则把角标数字改为指定的数字；为 0 表示清除
        /// </summary>
        public int Badge { get; set; }

        /// <summary>
        /// 校验参数
        /// </summary>
        /// <returns></returns>
        public string CheckParams()
        {
            string ret = "";

            if (PushType == 2 && string.IsNullOrEmpty(Tags))
                ret += ",用户标签不能为空";
            if (PushType == 3 && string.IsNullOrEmpty(Alias))
                ret += ",用户别名不能为空";
            if (PushType == 4 && string.IsNullOrEmpty(DeviceTokens))
                ret += ",注册ID不能为空";
            if (DeviceType < 1 || DeviceType > 3)
                ret += ",推送平台不正确";
            if (MsgType < 1 || MsgType > 2)
                ret += ",MsgType不正确";
            if (string.IsNullOrEmpty(Text) && string.IsNullOrEmpty(Alert))
                ret += ",Text和Alert不能同时为空";

            return ret;
        }
    }

    public class PushMsgInfo
    {
        public string id { get; private set; }
        public string type { get; set; }
        public PushMsgData data { get; set; }
        public string pushtime { get; private set; }
        public PushMsgInfo(string type, string alert, string title, string content)
        {
            this.id = NewMsgId();
            this.type = type;
            this.pushtime = Utils.GetUnixStamp(DateTime.Now).ToString();
            this.data = new PushMsgData();
            this.data.alert = string.IsNullOrEmpty(alert) ? "" : alert;
            this.data.title = string.IsNullOrEmpty(title) ? "" : title;
            this.data.content = string.IsNullOrEmpty(content) ? "" : content;
        }

        public static string NewMsgId()
        {
            return DateTime.Now.ToString("yyMMddHHmmss") + JpushBiz.Instance.Rnd.Next(1000000, 9999999);
        }
    }
    public class PushMsgData
    {
        public string alert { get; set; }
        public string title { get; set; }
        public string content { get; set; }
    }

}
